import com.sun.javafx.scene.input.InputEventUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: AliceMana
 * Date: 2022-10-09
 * Time: 21:45
 */
public class Test {
    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode() {}
        TreeNode(int val) { this.val = val; }
        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    // https://leetcode.cn/problems/binary-tree-preorder-traversal/
    // 二叉树实现非递归前序遍历
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        TreeNode cur = root;
        Stack<TreeNode> stack = new Stack<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.add(cur);
                list.add(cur.val);
                cur = cur.left;
            }

            TreeNode top = stack.pop();
            cur = top.right;
        }
        return list;
    }

    // https://leetcode.cn/problems/binary-tree-inorder-traversal/
    // 二叉树实现非递归中序遍历
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        TreeNode cur = root;
        Stack<TreeNode> stack = new Stack<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.add(cur);
                cur = cur.left;
            }

            TreeNode top = stack.pop();
            list.add(top.val);
            cur = top.right;
        }
        return list;
    }

    // https://leetcode.cn/problems/binary-tree-postorder-traversal/
    // 二叉树实现非递归后序遍历
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        TreeNode cur = root;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode prev = null;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.add(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if (top.right == null || top.right == prev) {
                list.add(top.val);
                stack.pop();
                prev = top;
            } else {
                cur = top.right;
            }
        }
        return list;
    }

    // https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
    public int preIndex = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeChild(preorder, inorder, 0, inorder.length-1);
    }
    public TreeNode buildTreeChild(int[] preorder, int[] inorder, int inBegin, int inEnd) {
        // 当前根节点没有左子树 或 右子树
        if(inBegin > inEnd) {
            return null;
        }
        // 创建根节点
        TreeNode root = new TreeNode(preorder[preIndex]);

        // 找到root在中序遍历中的位置
        int index = findIndex(inorder, inBegin, inEnd, preorder[preIndex]);
        preIndex++;
        if (index == -1) {
            return null;
        }

        // 构建左子树和右子树
        root.left = buildTreeChild(preorder, inorder, inBegin, index-1);
        root.right = buildTreeChild(preorder, inorder, index+1, inEnd);
        return root;
    }

    private int findIndex(int[] inorder, int inBegin, int inEnd, int val) {
        for (int i = inBegin; i <= inEnd; i++) {
            if (inorder[i] == val) {
                return i;
            }
        }
        return -1;
    }

    // https://leetcode.cn/problems/construct-string-from-binary-tree/

    public String tree2str(TreeNode root) {
        StringBuilder stringBuilder = new StringBuilder();
        tree2strChild(root, stringBuilder);
        return stringBuilder.toString();
    }
    private void tree2strChild(TreeNode root, StringBuilder stringBuilder) {
        if (root == null) {
            return;
        }

        stringBuilder.append(root.val);
        if (root.left != null) {
            stringBuilder.append("(");
            tree2strChild(root.left, stringBuilder);
            stringBuilder.append(")");
        } else {
            if (root.right == null) {
                return;
            } else {
                stringBuilder.append("()");
            }
        }
        if (root.right == null) {
            return;
        } else {
            stringBuilder.append("(");
            tree2strChild(root.right, stringBuilder);
            stringBuilder.append(")");
        }
    }
}
